home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / WASTE 1.2a4 / WASTE Demo / WEDemoMenus.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-05  |  22.0 KB  |  1,135 lines  |  [TEXT/CWIE]

  1. /*
  2.     WASTE Demo Project:
  3.     Menu Handling
  4.             
  5.     Copyright © 1993-1995 Marco Piovanelli
  6.     All Rights Reserved
  7.  
  8.     C port by John C. Daub
  9. */
  10.  
  11. #ifndef __ALIASES__
  12. #include <Aliases.h>
  13. #endif
  14. #ifndef __DEVICES__
  15. #include <Devices.h>
  16. #endif
  17. #ifndef __LOWMEM__
  18. #include <LowMem.h>
  19. #endif
  20. #ifndef __STANDARDFILE__
  21. #include <StandardFile.h>
  22. #endif
  23. #ifndef __TOOLUTILS__
  24. #include <ToolUtils.h>
  25. #endif
  26.  
  27. #ifndef __WEDEMOAPP__
  28. #include "WEDemoIntf.h"
  29. #endif
  30.  
  31. #include "WETabs.h"
  32.  
  33. // resource types
  34.  
  35. #define kTypeMenuColorTable        'mctb'
  36.  
  37. // static variables
  38.  
  39. static MenuCRsrcHandle        sColors;        // handle to the 'mctb' resource for the Color menu
  40. static ModalFilterYDUPP        sMySFDialogFilter; // static variable for exclusive use by GetMySFDialogFilter
  41.  
  42. // constants used by DoClose()
  43.  
  44. enum {
  45.     kButtonSave            = 1,
  46.     kButtonCancel,
  47.     kButtonDontSave
  48. };
  49.  
  50.  
  51.  
  52. void    SetDefaultDirectory( const FSSpec *spec )
  53. {
  54.     LMSetCurDirStore( spec->parID );
  55.     LMSetSFSaveDisk( -spec->vRefNum );
  56.     
  57.     return;
  58. }
  59.  
  60. // in the original WASTE Demo App code, Marco just had MySFDialogFilter() call
  61. // MyStandardDialogFilter().  However, due to how I extended the functionality
  62. // of MyStandardDialogFilter(), we cannot do that, hence we need another filter for
  63. // our SFDialogs.  (incidentally, this function is pretty much how Marco originally
  64. // wrote MyStandardDialogFilter(), if you're interested)
  65.  
  66. pascal Boolean MySFDialogFilter( DialogRef dialog, EventRecord *event, short *item, void *yourData )
  67. {
  68. #pragma unused ( yourData )
  69.  
  70.     GrafPtr                savePort;
  71.     ModalFilterUPP        stdFilter = NULL;
  72.     Boolean                reply = false;
  73.     OSErr                err;
  74.     
  75.     // set up the port
  76.     
  77.     GetPort( &savePort );
  78.     SetGrafPortOfDialog( dialog );
  79.     
  80.     //     intercept window events directed to widnows behind the dialog
  81.     
  82.     if ( ( event->what == updateEvt ) || ( event->what == activateEvt ) )
  83.     {
  84.         if ( (DialogRef)event->message != dialog )
  85.             DoWindowEvent( event );
  86.     }
  87.     
  88.     //    call the standard Dialog Manager filter procedure
  89.     
  90.  
  91.     err = GetStdFilterProc( &stdFilter );
  92.     if (err == noErr)
  93.         reply = CallModalFilterProc( stdFilter, dialog, event, item );
  94.     
  95.     //    restore the port
  96.     SetPort( savePort );
  97.     
  98.     return reply;
  99.  
  100. }
  101.  
  102.  
  103. pascal ModalFilterYDUPP GetMySFDialogFilter( void )
  104. {
  105.     if ( sMySFDialogFilter == NULL )
  106.         sMySFDialogFilter = NewModalFilterYDProc( MySFDialogFilter );
  107.     
  108.     return sMySFDialogFilter;
  109. }
  110.  
  111.  
  112. short    FindMenuItemText( MenuRef menu, ConstStr255Param stringToFind )
  113. {
  114.     short        item;
  115.     Str255        itemString;
  116.     
  117.     for ( item = CountMItems( menu ); item >= 1; item-- )
  118.     {
  119.         GetMenuItemText( menu, item, itemString );
  120.         if ( EqualString( itemString, stringToFind, false, false ) )
  121.             break;
  122.     }
  123.     
  124.     return item;
  125. }
  126.  
  127. Boolean    EqualColor( const RGBColor *rgb1, const RGBColor *rgb2 )
  128. {
  129.     return ( (rgb1->red == rgb2->red) && (rgb1->green == rgb2->green) && (rgb1->blue == rgb2->blue) );
  130. }
  131.  
  132.  
  133. void    PrepareMenus( void )
  134. {
  135.     WindowRef        window;
  136.     WEReference        we;
  137.     MenuRef            menu;
  138.     short            item;
  139.     Str255            itemText;
  140.     long            selStart, selEnd;
  141.     WEActionKind    actionKind;
  142.     short            mode;
  143.     TextStyle        ts;
  144.     Boolean            temp;
  145.     
  146.     // get a pointer to the frontmost window, if any
  147.     
  148.     window = FrontWindow();
  149.     
  150.     // get associated WE instance
  151.     
  152.     we = GetWindowWE(window);
  153.     
  154.     // *** FILE MENU ***
  155.     
  156.     menu = GetMenuHandle( kMenuFile );
  157.     
  158.     // first disable all items
  159.     
  160.     for ( item = CountMItems( menu); item >= 1; item-- )
  161.         DisableItem( menu, item );
  162.     
  163.     // New, Open, and Quit are always enabled
  164.     
  165.     EnableItem( menu, kItemNew );
  166.     EnableItem( menu, kItemOpen );
  167.     EnableItem( menu, kItemQuit );
  168.     
  169.     // enable Close and Save As if there is an active window
  170.     
  171.     if ( window != NULL )
  172.     {
  173.         EnableItem( menu, kItemClose );
  174.         EnableItem( menu, kItemSaveAs );
  175.         
  176.         // enable Save is the active window is dirty
  177.         
  178.         if ( WEGetModCount( we ) > 0 )
  179.             EnableItem( menu, kItemSave );
  180.     }
  181.     
  182.     // *** EDIT MENU ***
  183.     
  184.     menu = GetMenuHandle( kMenuEdit );
  185.         
  186.     // first, disable all items
  187.     
  188.     for ( item = CountMItems( menu ); item >= 1; item-- )
  189.         DisableItem( menu, item );
  190.     
  191.     // by default, the Undo menu item should read "Can't Undo"
  192.     
  193.     GetIndString( itemText, kUndoStringsID, 1 );
  194.     SetMenuItemText( menu, kItemUndo, itemText );
  195.     
  196.     if ( window != NULL )
  197.     {
  198.         // enable Paste if there's anything pasteable on the Clipboard
  199.         
  200.         if ( WECanPaste( we ) )
  201.             EnableItem( menu, kItemPaste );
  202.         
  203.         // enable Undo if anything can be undone
  204.         
  205.         actionKind = WEGetUndoInfo( &temp, we );
  206.         
  207.         if ( actionKind != weAKNone )
  208.         {
  209.             EnableItem( menu, kItemUndo );
  210.             
  211.             // change the Undo menu item to "Undo/Redo" + name of action to undo/redo
  212.             // the funky ?: thing is to replicate the Pascal ORD() function
  213.             
  214.             GetIndString( itemText, kUndoStringsID, 2 * actionKind + ( temp ? 1 : 0 ) );
  215.             SetMenuItemText( menu, kItemUndo, itemText );
  216.         }
  217.         
  218.         // enable Select All if there is anything to select
  219.         
  220.         if ( WEGetTextLength( we ) > 0 )
  221.             EnableItem( menu, kItemSelectAll );
  222.             
  223.         // get the current selection range
  224.         
  225.         WEGetSelection( &selStart, &selEnd, we );
  226.         if ( selStart != selEnd )
  227.         {
  228.             // enable Cut, Copy, and Clear if the selection range is not empty
  229.             
  230.             EnableItem( menu, kItemCut );
  231.             EnableItem( menu, kItemCopy );
  232.             EnableItem( menu, kItemClear );
  233.         }
  234.         
  235.         // determine which style attributes are continuous over the current selection range
  236.         // we'll need this information in order to check the Font/Size/Style/Color menus properly
  237.         
  238.         mode = weDoAll;  // query about all attributes
  239.         temp = WEContinuousStyle( &mode, &ts, we );
  240.         
  241.     }
  242.     else
  243.         mode = 0;  // no window, so check no items
  244.     
  245.     // *** FONT MENU ***
  246.     
  247.     menu = GetMenuHandle( kMenuFont );
  248.     
  249.     // first, remove all check marks
  250.     
  251.     for ( item = CountMItems( menu ); item >= 1; item-- )
  252.         CheckItem( menu, item, false );
  253.     
  254.     // if there is a continuous font all over the selection range, check the
  255.     // corresponding menu item
  256.     
  257.     if ( (BAND( mode, weDoFont )) != 0 )
  258.     {
  259.         GetFontName( ts.tsFont, itemText );
  260.         CheckItem( menu, FindMenuItemText( menu, itemText ), true );
  261.     }
  262.     
  263.     // *** SIZE MENU ***
  264.     
  265.     menu = GetMenuHandle( kMenuSize );
  266.     
  267.     // first, remove all check marks
  268.     
  269.     for ( item = CountMItems( menu ); item >= 1; item-- )
  270.         CheckItem( menu, item, false );
  271.     
  272.     // if tehre is a continuous font size all over the selection range
  273.     // check the corresponding menu item
  274.     
  275.     if ( BAND( mode, weDoSize ) != 0 )
  276.     {
  277.         NumToString( ts.tsSize, itemText );
  278.         CheckItem( menu, FindMenuItemText( menu, itemText ), true );
  279.     }
  280.     
  281.     // *** STYLE MENU ***
  282.     
  283.     menu = GetMenuHandle( kMenuStyle );
  284.     
  285.     // first, remove all check marks
  286.     for ( item = CountMItems( menu ); item >= 1; item-- )
  287.         CheckItem( menu, item, false );
  288.         
  289.     // check the style menu items corresponding to style attributes
  290.     
  291.     if ( BAND( mode, weDoFace ) != 0 )
  292.     {
  293.         if ( ts.tsFace == 0 )
  294.             CheckItem( menu, kItemPlainText, true );
  295.         
  296.         if ( ts.tsFace & bold )
  297.             CheckItem( menu, kItemBold, true );
  298.         
  299.         if ( ts.tsFace & italic )
  300.             CheckItem( menu, kItemItalic, true );
  301.         
  302.         if ( ts.tsFace & underline )
  303.             CheckItem( menu, kItemUnderline, true );
  304.         
  305.         if ( ts.tsFace & outline )
  306.             CheckItem( menu, kItemOutline, true );
  307.         
  308.         if ( ts.tsFace & shadow )
  309.             CheckItem( menu, kItemShadow, true );
  310.         
  311.         if ( ts.tsFace & condense )
  312.             CheckItem( menu, kItemCondensed, true );
  313.         
  314.         if ( ts.tsFace & extend )
  315.             CheckItem( menu, kItemExtended, true );
  316.         
  317.     }
  318.     
  319.     // *** COLOR MENU ***
  320.     
  321.     menu = GetMenuHandle( kMenuColor );
  322.     
  323.     // first, remove all check marks
  324.     
  325.     for ( item = CountMItems( menu ); item >= 1; item-- )
  326.         CheckItem( menu, item, false );
  327.     
  328.     // if there is a continuous color all over the selection range,
  329.     // check the corresponding menu item (if any )
  330.  
  331.     if ( BAND( mode, weDoColor) != 0 )
  332.     {
  333.         for ( item = (*sColors)->numEntries - 1; item >= 0; item-- )
  334.         {
  335.             if ( EqualColor( &ts.tsColor, & (*sColors)->mcEntryRecs[item].mctRGB2 ) )
  336.             {
  337.                 CheckItem( menu, (*sColors)->mcEntryRecs[item].mctItem, true );
  338.             }    
  339.     
  340.         } // end for loop
  341.     }
  342.     
  343.     // *** FEATURES MENU ***
  344.     
  345.     menu = GetMenuHandle( kMenuFeatures );
  346.     
  347.     // first remove all check marks (except the first item, which has a submenu!!)
  348.     
  349.     for ( item = CountMItems( menu ); item >= 2; item-- )
  350.         CheckItem( menu, item, false );
  351.     
  352.     if ( window != NULL )
  353.     {
  354.         // mark each item according to the corresponding feature
  355.         
  356.         if ( WEIsTabHooks( we ) )
  357.         {
  358.             CheckItem( menu, kItemTabHooks, true );
  359.             DisableItem( menu, kItemAlignment );
  360.         }
  361.         else
  362.             EnableItem( menu, kItemAlignment );
  363.         
  364.         if ( WEFeatureFlag( weFAutoScroll, weBitTest, we ) )
  365.             CheckItem( menu, kItemAutoScroll, true );
  366.         
  367.         if ( WEFeatureFlag( weFOutlineHilite, weBitTest, we ))
  368.             CheckItem( menu, kItemOutlineHilite, true );
  369.         
  370.         if ( WEFeatureFlag( weFReadOnly, weBitTest, we ))
  371.             CheckItem( menu, kItemReadOnly, true );
  372.         
  373.         if ( WEFeatureFlag( weFIntCutAndPaste, weBitTest, we ))
  374.             CheckItem( menu, kItemIntCutAndPaste, true );
  375.         
  376.         if ( WEFeatureFlag( weFDragAndDrop, weBitTest, we ))
  377.             CheckItem( menu, kItemDragAndDrop, true );
  378.         
  379.         if ( WEFeatureFlag( weFDrawOffscreen, weBitTest, we ) )
  380.             CheckItem( menu, kItemOffscreenDrawing, true );
  381.     }
  382.     
  383.     // *** ALIGNMENT MENU ***
  384.     
  385.     menu = GetMenuHandle( kMenuAlignment );
  386.     
  387.     // first, remove all check marks
  388.     
  389.     for ( item = CountMItems( menu ); item >= 1; item-- )
  390.         CheckItem( menu, item, false );
  391.     
  392.     if ( window != NULL )
  393.     {
  394.         // find the Aligment menu item corresponding to mthe current alignment state
  395.         
  396.         switch ( WEGetAlignment( we ) )
  397.         {
  398.             case weFlushLeft:
  399.                 item = kItemAlignLeft;
  400.             break;
  401.             
  402.             case weFlushRight:
  403.                 item = kItemAlignRight;
  404.             break;
  405.             
  406.             case weFlushDefault:
  407.                 item = kItemAlignDefault;
  408.             break;
  409.             
  410.             case weCenter:
  411.                 item = kItemCenter;
  412.             break;
  413.             
  414.             case weJustify:
  415.                 item = kItemJustify;
  416.             break;
  417.             
  418.             default:
  419.                 ;  // nada
  420.         }
  421.         
  422.         // check the menu item
  423.         
  424.         CheckItem( menu, item, true );
  425.     }
  426.     
  427.     return;
  428. }
  429.  
  430.  
  431. void    DoDeskAcc( short menuItem )
  432. {
  433.     Str255        daName;
  434.     short        daNumber;
  435.     
  436.     GetMenuItemText( GetMenuHandle( kMenuApple ), menuItem, daName );
  437.     daNumber = OpenDeskAcc( daName );
  438.     
  439.     return;
  440. }
  441.  
  442.  
  443. OSErr    DoNew( void )
  444. {
  445.     // create a new window from scratch
  446.     
  447.     return CreateWindow( NULL );
  448. }
  449.  
  450.  
  451. OSErr    DoOpen( void )
  452. {
  453.     StandardFileReply        reply;
  454.     SFTypeList                typeList;
  455.     OSErr                    err = noErr;
  456.     Point                    where = { -1, -1 };  // auto center dialog
  457.     
  458.     // set up a list of file types we can open for StandardGetFile
  459.     
  460.     typeList[0] = kTypeText;
  461.     typeList[1] = kTypeTextReadOnly;
  462.     
  463.     // put up the standard open dialog box.
  464.     // (we use CustomGetFile instead of StandardGetFile because we want to provide
  465.     // our own dialog filter procedure that takes care of updating our windows)
  466.     
  467.     CustomGetFile( NULL, 1, typeList, &reply, 0, where, NULL, GetMySFDialogFilter(), NULL, NULL, NULL );
  468.     
  469.     // if the user ok'ed the dialog, create a new window from the specified file
  470.     
  471.     if ( reply.sfGood )
  472.         err = CreateWindow( &reply.sfFile );
  473.     else
  474.         err = userCanceledErr;
  475.     
  476.     return err;
  477. }
  478.  
  479.  
  480. OSErr        SaveWindow( const FSSpec *pFileSpec, WindowRef window )
  481. {
  482.     DocumentHandle    hDocument;
  483.     AliasHandle        aHandle;
  484.     OSErr            err;
  485.     
  486.     hDocument = GetWindowDocument(window);
  487.     
  488.     ForgetHandle( & (*hDocument)->fileAlias );
  489.     
  490.     // svae the text
  491.     
  492.     err = WriteTextFile( pFileSpec, (*hDocument)->we );
  493.     if ( err == noErr )
  494.     {
  495.         SetWTitle( window, pFileSpec->name );
  496.         
  497.         // replace the old window alias (if any) with a new one created from pFileSpec
  498.         
  499.         ForgetHandle( & (* hDocument)->fileAlias );
  500.         err = NewAlias( NULL, pFileSpec, &aHandle );
  501.         // if err, aHandle will be NULL, and it's not fatal, just will make subsequent saves annoying
  502.         (* hDocument)->fileAlias = (Handle)aHandle;
  503.     }
  504.     
  505.     return err;
  506. }
  507.  
  508.  
  509. OSErr    DoSaveAs( const FSSpec *suggestedTarget, WindowRef window )
  510. {
  511.     StringHandle        hPrompt;
  512.     Str255                defaultName;
  513.     StandardFileReply    reply;
  514.     Point                where = { -1, -1 }; // autocenter's dialog
  515.     OSErr                err;
  516.     
  517.     
  518.     // get the prompt string for CustomPutFile from a 'STR ' resource and lock it
  519.     
  520.     hPrompt = GetString( kPromptStringID );
  521.     HLockHi( (Handle)hPrompt );
  522.     
  523.     // if a suggested target file is provided, use its name as the default name
  524.     
  525.     if ( suggestedTarget != NULL )
  526.     {
  527.         PStringCopy( suggestedTarget->name, defaultName );
  528.         SetDefaultDirectory( suggestedTarget );
  529.     }
  530.     else
  531.         // otherwise use the window title as default name for CustomPutFile
  532.         GetWTitle( window, defaultName );
  533.     
  534.     // put up the standard Save dialog box
  535.     
  536.     CustomPutFile( *hPrompt, defaultName, &reply, 0, where, NULL, GetMySFDialogFilter(), NULL, NULL, NULL );
  537.     
  538.     // unlock the string resource
  539.     
  540.     HUnlock( (Handle)hPrompt );
  541.     
  542.     // if the user ok'ed the dialog, save the window to the specified file
  543.     
  544.     if ( reply.sfGood )
  545.         err = SaveWindow( &reply.sfFile, window );
  546.     else
  547.         err = userCanceledErr;
  548.     
  549.     return err;
  550. }
  551.  
  552.  
  553. OSErr    DoSave( WindowRef window )
  554. {
  555.     FSSpec        spec;
  556.     FSSpecPtr    suggestedTarget = NULL;
  557.     Boolean        promptForNewFile = true, aliasTargetWasChanged;
  558.     OSErr        err;
  559.     
  560.     // resolve the alias associated with this window, if any
  561.     
  562.     if ( (* GetWindowDocument(window))->fileAlias != NULL )
  563.     {
  564.         if ( ( ResolveAlias( NULL, ((AliasHandle)(* GetWindowDocument(window))->fileAlias), &spec, &aliasTargetWasChanged ) == noErr ) )
  565.         {
  566.             if ( aliasTargetWasChanged )
  567.                 suggestedTarget = &spec;
  568.             else
  569.                 promptForNewFile = false;
  570.         }
  571.     }
  572.     
  573.     // if no file has been previously associated with this window, or if the
  574.     // alias resolution has failed, or if the alias target was changed
  575.     // prompt the user for a new destination
  576.     
  577.     if ( promptForNewFile )
  578.         err = DoSaveAs( suggestedTarget, window );
  579.     else
  580.         err = SaveWindow( &spec, window );
  581.     
  582.     return err;
  583. }
  584.  
  585.  
  586.  
  587. OSErr        DoClose( ClosingOption closing, SavingOption saving, WindowRef window )
  588. {
  589.     Str255        s1, s2;
  590.     short        alertResult;
  591.     OSErr        err = noErr;
  592.     
  593.     // is this window dirty?
  594.     
  595.     if ( WEGetModCount( GetWindowWE(window) ) > 0 )
  596.     {
  597.         // do we have to ask the user whether to save changes?
  598.         
  599.         if ( saving == savingAsk )
  600.         {
  601.             // prepare the parametric strings to be used in the Save Changes alert box
  602.             
  603.             GetWTitle( window, s1 );
  604.             // added this in over Marco's code - JCD
  605.             
  606.             if ( s1 == "\p" )  // if NULL
  607.                 PStringCopy( "\puntitled", s1 );
  608.                 
  609.             GetIndString( s2, kClosingQuittingStringsID, 1 + (closing ? 1 : 0 ) );
  610.             ParamText( s1, s2, "\p", "\p" );
  611.             
  612.             // put up the Save Changes? alert box
  613.             
  614.             SetCursor( &qd.arrow );
  615.             
  616.             alertResult = Alert( kAlertSaveChanges, GetMyStandardDialogFilter() );
  617.             
  618.             // exit if the user canceled the alert box
  619.             
  620.             if ( alertResult == kButtonCancel )
  621.                 return userCanceledErr;
  622.             
  623.             if ( alertResult == kButtonSave )
  624.                 saving = savingYes;
  625.             else
  626.                 saving = savingNo;
  627.         }
  628.         
  629.         if ( saving == savingYes )
  630.         {
  631.             err = DoSave( window );
  632.             
  633.             if ( err != noErr )
  634.                 return err;
  635.             
  636.         }
  637.     }
  638.     
  639.     // destroy the window
  640.     
  641.     DestroyWindow( window );
  642.     
  643.     return err;
  644. }
  645.  
  646.  
  647.  
  648. OSErr    DoQuit( SavingOption saving )
  649. {
  650.     WindowRef        window;
  651.     OSErr            err = noErr;
  652.     
  653.     // close all windows
  654.     
  655.     do
  656.     {
  657.         window = FrontWindow();
  658.         if ( window != NULL )
  659.         {
  660.             err = DoClose( closingApplication, saving, window );
  661.             if ( err != noErr )
  662.                 return err;
  663.         }
  664.     } while ( window );
  665.     
  666.     // set a flag so we drop out of the event loop
  667.     
  668.     gExiting = true;
  669.     
  670.     return err;
  671. }
  672.  
  673.  
  674. void    DoAppleChoice( short menuItem )
  675. {
  676.     if ( menuItem == kItemAbout )
  677.         DoAboutBox( kDialogAboutBox );
  678.     else
  679.         DoDeskAcc( menuItem );
  680.     
  681.     return;
  682. }
  683.  
  684.  
  685. void    DoFileChoice( short menuItem )
  686. {
  687.     WindowRef        window = FrontWindow();
  688.     
  689.     switch( menuItem )
  690.     {
  691.         case kItemNew:
  692.             if ( DoNew() != noErr )
  693.                 ;
  694.         break;
  695.         
  696.         case kItemOpen:
  697.             if ( DoOpen() != noErr )
  698.                 ;
  699.         break;
  700.         
  701.         case kItemClose:
  702.             if ( DoClose( closingWindow, savingAsk, window ) != noErr )
  703.                 ;
  704.         break;
  705.         
  706.         case kItemSave:
  707.             if ( DoSave( window ) != noErr )
  708.                 ;
  709.         break;
  710.         
  711.         case kItemSaveAs:
  712.             if ( DoSaveAs( NULL, window ) != noErr )
  713.                 ;
  714.         break;
  715.         
  716.         case kItemQuit:
  717.             if ( DoQuit( savingAsk ) != noErr )
  718.                 ;
  719.         break;
  720.         
  721.         default:
  722.             ;
  723.         break;
  724.     }
  725.     
  726.     return;
  727. }
  728.  
  729.  
  730. void    DoEditChoice( short menuItem )
  731. {
  732.     WindowRef        window;
  733.     WEReference        we;
  734.     
  735.     // do nothing is no window is active
  736.     
  737.     window = FrontWindow();
  738.     if ( window == NULL )
  739.         return;
  740.     
  741.     we = GetWindowWE(window);
  742.     
  743.     switch ( menuItem )
  744.     {
  745.         case kItemUndo:
  746.             if ( WEUndo(we) != noErr )
  747.                 ;
  748.         break;
  749.         
  750.         case kItemCut:
  751.             if ( WECut( we) != noErr )
  752.                 ;
  753.         break;
  754.         
  755.         case  kItemCopy:
  756.             if ( WECopy( we ) != noErr )
  757.                 ;
  758.         break;
  759.         
  760.         case kItemPaste:
  761.             if ( WEPaste( we ) != noErr )
  762.                 ;
  763.         break;
  764.         
  765.         case kItemClear:
  766.             if ( WEDelete( we ) != noErr )
  767.                 ;
  768.         break;
  769.         
  770.         case kItemSelectAll:
  771.             WESetSelection( 0, LONG_MAX, we );
  772.         break;
  773.         
  774.         default:
  775.             ;
  776.         break;
  777.     }
  778.     
  779.     return;
  780. }
  781.  
  782.  
  783. void    DoFontChoice( short menuItem )
  784. {
  785.     WindowRef        window;
  786.     Str255            fontName;
  787.     TextStyle        ts;
  788.     
  789.     window = FrontWindow();
  790.     if ( window != NULL )
  791.     {
  792.         GetMenuItemText( GetMenuHandle( kMenuFont ), menuItem, fontName );
  793.         GetFNum( fontName, &ts.tsFont );
  794.         if ( WESetStyle( weDoFont, &ts, GetWindowWE(window) ) != noErr )
  795.             ;
  796.     }
  797.     
  798.     return;
  799. }
  800.  
  801.  
  802. void    DoSizeChoice( short menuItem )
  803. {
  804.     WindowRef        window = FrontWindow();
  805.     Str255            sizeString;
  806.     long            longSize;
  807.     short            mode;
  808.     TextStyle        ts;
  809.     
  810.     if ( window != NULL )
  811.     {
  812.         if ( menuItem <= kItemLastSize )
  813.         {
  814.             GetMenuItemText( GetMenuHandle( kMenuSize ), menuItem, sizeString );
  815.             StringToNum( sizeString, &longSize );
  816.             mode = weDoSize;
  817.             ts.tsSize = longSize;
  818.         }
  819.         else if ( menuItem == kItemSmaller )
  820.         {
  821.             mode = weDoAddSize;
  822.             ts.tsSize = -1;
  823.         }
  824.         else if ( menuItem == kItemLarger )
  825.         {
  826.             mode = weDoAddSize;
  827.             ts.tsSize = 1;
  828.         }
  829.         
  830.         if ( WESetStyle( mode, &ts, GetWindowWE(window) ) != noErr )
  831.             ;
  832.     }
  833.     
  834.     return;
  835. }
  836.  
  837.  
  838. void    DoStyleChoice( short menuItem )
  839. {
  840.     WindowRef        window = FrontWindow();
  841.     TextStyle        ts;
  842.     
  843.     if ( window != NULL )
  844.     {
  845.         switch( menuItem )
  846.         {
  847.             case kItemPlainText:
  848.                 ts.tsFace = 0;
  849.             break;
  850.             
  851.             case kItemBold:
  852.                 ts.tsFace = bold;
  853.             break;
  854.             
  855.             case kItemItalic:
  856.                 ts.tsFace = italic;
  857.             break;
  858.             
  859.             case kItemUnderline:
  860.                 ts.tsFace = underline;
  861.             break;
  862.             
  863.             case kItemOutline:
  864.                 ts.tsFace = outline;
  865.             break;
  866.             
  867.             case kItemShadow:
  868.                 ts.tsFace = shadow;
  869.             break;
  870.             
  871.             case kItemCondensed:
  872.                 ts.tsFace = condense;
  873.             break;
  874.             
  875.             case kItemExtended:
  876.                 ts.tsFace = extend;
  877.             break;
  878.             
  879.             default:
  880.                 ;
  881.         }
  882.         
  883.         if ( WESetStyle( weDoFace + weDoToggleFace, &ts, GetWindowWE(window)) != noErr )
  884.             ;
  885.     }
  886.     
  887.     return;
  888. }
  889.  
  890.  
  891. void    DoColorChoice( short menuItem )
  892. {
  893.     WindowRef            window = FrontWindow();
  894.     short                i;
  895.     TextStyle            ts;
  896.     
  897.     // do nothing if there is no front window
  898.     
  899.     if ( window == NULL )
  900.         return;
  901.     
  902.     // find the color corresponding to the chosen menu item
  903.     
  904.     for ( i = (*sColors)->numEntries - 1; i >= 0; i-- )
  905.     {
  906.         if ( (*sColors)->mcEntryRecs[i].mctItem == menuItem )
  907.         {
  908.             ts.tsColor = (*sColors)->mcEntryRecs[i].mctRGB2;
  909.             if ( WESetStyle( weDoColor, &ts, GetWindowWE(window) ) != noErr )
  910.                 ;
  911.         }
  912.     }
  913.     
  914.     return;
  915. }
  916.  
  917.  
  918. void    DoAlignChoice( short menuItem )
  919. {
  920.     WindowRef        window = FrontWindow();
  921.     SignedByte        alignment;
  922.     
  923.     if ( window != NULL )
  924.     {
  925.         switch( menuItem )
  926.         {
  927.             case kItemAlignDefault:
  928.                 alignment = weFlushDefault;
  929.             break;
  930.             
  931.             case kItemAlignLeft:
  932.                 alignment = weFlushLeft;
  933.             break;
  934.             
  935.             case kItemCenter:
  936.                 alignment = weCenter;
  937.             break;
  938.             
  939.             case kItemAlignRight:
  940.                 alignment = weFlushRight;
  941.             break;
  942.             
  943.             case kItemJustify:
  944.                 alignment = weJustify;
  945.             break;
  946.             
  947.             default:
  948.                 return;
  949.             break;
  950.         }
  951.         
  952.         // set the alignment mode (this automatically redraws the text)
  953.         
  954.         WESetAlignment( alignment, GetWindowWE(window) );
  955.     }
  956.     
  957.     return;
  958. }
  959.  
  960.  
  961. void    DoFeatureChoice( short menuItem )
  962. {
  963.     WindowRef        window = FrontWindow();
  964.     WEReference        we;
  965.     short            feature, oldSetting;
  966.     
  967.     if ( window == NULL )
  968.         return;
  969.     
  970.     we = GetWindowWE(window);
  971.     
  972.     if ( menuItem == kItemTabHooks )
  973.     {
  974.         // install or remove our custom tab hooks
  975.         
  976.         if ( WEIsTabHooks( we ) == false )
  977.         {
  978.             // left-align the text (the hooks only work with left-aligned text )
  979.             WESetAlignment( weFlushLeft, we );
  980.             
  981.             // install tab hooks
  982.             WEInstallTabHooks( we );
  983.         }
  984.         else
  985.         {
  986.             // remove tab hooks
  987.             WERemoveTabHooks( we );
  988.         }
  989.         
  990.         // turn the cursor into a wristwatch
  991.         
  992.         SetCursor( *(GetCursor( watchCursor) ) );
  993.         
  994.         // recalculate link breaks and redraw the text
  995.         
  996.         if ( WECalText( we ) != noErr )
  997.             ;
  998.     }
  999.     else
  1000.     {
  1001.         switch ( menuItem )
  1002.         {
  1003.             case kItemAutoScroll:
  1004.                 feature = weFAutoScroll;
  1005.             break;
  1006.             
  1007.             case kItemOutlineHilite:
  1008.                 feature = weFOutlineHilite;
  1009.             break;
  1010.             
  1011.             case kItemReadOnly:
  1012.                 feature = weFReadOnly;
  1013.             break;
  1014.             
  1015.             case kItemIntCutAndPaste:
  1016.                 feature = weFIntCutAndPaste;
  1017.             break;
  1018.             
  1019.             case kItemDragAndDrop:
  1020.                 feature = weFDragAndDrop;
  1021.             break;
  1022.             
  1023.             case kItemOffscreenDrawing:
  1024.                 feature = weFDrawOffscreen;
  1025.             break;
  1026.             
  1027.             default:
  1028.                 ;
  1029.             break;
  1030.         }
  1031.         
  1032.         // toggle the specified feature
  1033.         
  1034.         oldSetting = WEFeatureFlag( feature, weBitToggle, we );
  1035.     }
  1036.     
  1037.     return;
  1038. }
  1039.  
  1040.  
  1041. void    DoMenuChoice( long menuChoice )
  1042. {
  1043.     short        menuID, menuItem;
  1044.     
  1045.     // extract menu ID and menu item from menuChoice
  1046.     
  1047.     menuID = HiWrd( menuChoice );
  1048.     menuItem = LoWrd( menuChoice );
  1049.     
  1050.     // dispatch on menuID
  1051.     
  1052.     switch( menuID )
  1053.     {
  1054.         case kMenuApple:
  1055.             DoAppleChoice( menuItem );
  1056.         break;
  1057.         
  1058.         case kMenuFile:
  1059.             DoFileChoice( menuItem );
  1060.         break;
  1061.         
  1062.         case kMenuEdit:
  1063.             DoEditChoice( menuItem );
  1064.         break;
  1065.         
  1066.         case kMenuFont:
  1067.             DoFontChoice( menuItem );
  1068.         break;
  1069.         
  1070.         case kMenuSize:
  1071.             DoSizeChoice( menuItem );
  1072.         break;
  1073.         
  1074.         case kMenuStyle:
  1075.             DoStyleChoice( menuItem );
  1076.         break;
  1077.         
  1078.         case kMenuColor:
  1079.             DoColorChoice( menuItem );
  1080.         break;
  1081.         
  1082.         case kMenuFeatures:
  1083.             DoFeatureChoice( menuItem );
  1084.         break;
  1085.         
  1086.         case kMenuAlignment:
  1087.             DoAlignChoice( menuItem );
  1088.         break;
  1089.         
  1090.         default:
  1091.             ;
  1092.     }
  1093.     
  1094.     HiliteMenu( 0 );
  1095.     
  1096.     return;
  1097. }
  1098.  
  1099.  
  1100. OSErr    InitializeMenus( void )
  1101. {
  1102.     OSErr        err = noErr;
  1103.     
  1104.     // build up the whole menu bar from the 'MBAR' resource
  1105.     
  1106.     SetMenuBar( GetNewMBar( kMenuBarID ) );
  1107.     
  1108.     // add names to the apple and Font menus
  1109.     
  1110.     AppendResMenu( GetMenuHandle( kMenuApple ), kTypeDeskAccessory );
  1111.     AppendResMenu( GetMenuHandle( kMenuFont ), kTypeFont );
  1112.     
  1113.     // insert the alignment subment into the hierarchical portion of the menu list
  1114.     InsertMenu( GetMenu( kMenuAlignment), -1 );
  1115.     
  1116.     // disable the "Drag and Drop Editing" item in the Features menu once and for all
  1117.     // if the Drag Manager isn't available
  1118.     
  1119.     if ( gHasDragAndDrop == false )
  1120.         DisableItem( GetMenuHandle( kMenuFeatures ), kItemDragAndDrop );
  1121.     
  1122.     // load the menu color table for the color menu
  1123.     
  1124.     sColors = (MenuCRsrcHandle)GetResource( kTypeMenuColorTable, kMenuColor );
  1125.     err = ResError();
  1126.     if ( err != noErr )
  1127.         return err;
  1128.     HNoPurge( (Handle)sColors );
  1129.     
  1130.     // draw the menu bar
  1131.     
  1132.     DrawMenuBar();
  1133.     
  1134.     return err;
  1135. }